﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;

namespace System
{
    public class TouchScrollingHelper
    {
        /// <summary>
        /// 已注册的控件
        /// </summary>
        private static readonly Dictionary<Type, int> _bindedUIElements = new Dictionary<Type, int>();
        private static (ScrollViewer, TouchCapture, int) _captures;
        private const int _MinValue = 10;
        private static bool _isMoveValue;
        public static readonly RoutedEvent TouchClickEvent = EventManager.RegisterRoutedEvent("TouchClick", RoutingStrategy.Bubble, typeof(RoutedEventHandler), typeof(UIElement));

        /// <summary>
        /// 注册列表控件
        /// </summary>
        /// <typeparam name="T">类型</typeparam>
        /// <param name="value">忽略值</param>
        public static void Register<T>(int value) where T : UIElement
        {
            var tempType = typeof(T);
            if (!_bindedUIElements.ContainsKey(tempType) && value >= _MinValue)
            {
                try
                {
                    EventManager.RegisterClassHandler(tempType, UIElement.PreviewTouchDownEvent, new EventHandler<TouchEventArgs>(UIElement_PreviewTouchDown), true);
                    EventManager.RegisterClassHandler(tempType, UIElement.PreviewTouchUpEvent, new EventHandler<TouchEventArgs>(UIElement_PreviewTouchUp), true);
                    EventManager.RegisterClassHandler(tempType, UIElement.PreviewTouchMoveEvent, new EventHandler<TouchEventArgs>(UIElement_TouchMove), true);
                }
                catch (Exception)
                {

                }
            }
            _bindedUIElements[tempType] = value < _MinValue ? _MinValue : value;
        }

        private static void UIElement_PreviewTouchDown(object sender, TouchEventArgs e)
        {
            _isMoveValue = false;
            if (sender is UIElement tempUIElement && _bindedUIElements.TryGetValue(sender.GetType(), out int value))
            {
                tempUIElement.SetCurrentValue(VirtualizingPanel.ScrollUnitProperty, ScrollUnit.Pixel);
                tempUIElement.SetCurrentValue(ScrollViewer.PanningModeProperty, PanningMode.VerticalFirst);
                var _ScrollViewer = tempUIElement.GetChildObject<ScrollViewer>();
                _captures = (_ScrollViewer, new TouchCapture
                {
                    VerticalOffset = _ScrollViewer.VerticalOffset,
                    HorizontalOffset = _ScrollViewer.HorizontalOffset,
                    Point = e.GetTouchPoint(_ScrollViewer).Position,
                }, value);
            }
            else
            {
                _captures = (null, new TouchCapture { HorizontalOffset = 0, VerticalOffset = 0, Point = new Point() }, _MinValue);
            }
        }

        private static void UIElement_TouchMove(object sender, TouchEventArgs e)
        {
            if (sender is UIElement tempUI && _captures.Item1 != null)
            {
                var capture = _captures.Item2;
                var _ScrollViewer = _captures.Item1;
                var point = e.GetTouchPoint(tempUI).Position;

                var dy = point.Y - capture.Point.Y;
                var dx = point.X - capture.Point.X;

                if (Math.Abs(dx) > _captures.Item3)
                {
                    _isMoveValue = true;
                    _ScrollViewer.ScrollToHorizontalOffset(capture.HorizontalOffset - dx);
                }
                if (Math.Abs(dy) > _captures.Item3)
                {
                    _isMoveValue = true;
                    _ScrollViewer.CaptureTouch(e.TouchDevice);
                    _ScrollViewer.ScrollToVerticalOffset(capture.VerticalOffset - dy);
                }
            }
        }

        private static void UIElement_PreviewTouchUp(object sender, TouchEventArgs e)
        {
            _captures.Item1?.ReleaseTouchCapture(e.TouchDevice);
            if (sender is UIElement tempUI)
            {
                if (_isMoveValue)
                {
                    //.net 4.7
                    //Windows 10 Creators Update 1703 10.0.15063
                    //EnablePointerSupport=true
                    tempUI.Focus();
                }
                else
                {
                    OnTouchClickEvent(tempUI);
                }
            }
        }

        private async static void OnTouchClickEvent(UIElement tempUI)
        {
            await Task.Delay(10);
            RoutedEventArgs arg = new RoutedEventArgs(TouchClickEvent, tempUI);
            tempUI?.RaiseEvent(arg);
        }

        internal class TouchCapture
        {
            public double VerticalOffset { get; set; }
            public double HorizontalOffset { get; set; }

            public Point Point { get; set; }
        }
    }

}
